package cn.com.yusys.yusp.admin.service.impl;

import java.util.*;

import cn.com.yusys.yusp.admin.service.UserServicePlus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.yusys.yusp.admin.repository.mapper.AdminSmInstuMapper;
import cn.com.yusys.yusp.admin.repository.mapper.UserCacheMapper;
import cn.com.yusys.yusp.commons.dto.def.ContrBean;
import cn.com.yusys.yusp.commons.dto.def.DataContrDTO;
import cn.com.yusys.yusp.commons.dto.def.MenuContrDTO;
import cn.com.yusys.yusp.commons.dto.def.ObjBean;
import cn.com.yusys.yusp.commons.dto.def.UserInfoDTO;
import cn.com.yusys.yusp.commons.service.UserService;
import cn.com.yusys.yusp.uaa.security.AuthUtils;

@Service
public class UserServiceImpl implements UserServicePlus {

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserCacheMapper userCacheMapper;

    @Override
    @Transactional(readOnly = true)
    @Cacheable(value = "contrurl", key = "'findAllContrUrl'", unless = "#result == null")
    public List<ContrBean> findAllContrUrl(String accessToken) {
        return userCacheMapper.selectAllContr();
    }
    @CacheEvict(value = "contrurl", key = "'findAllContrUrl'", beforeInvocation = true)
    public void cleanAllContrUrl() {
    	
    }
    @Override
    @Transactional(readOnly = true)
    @Cacheable(value = "sessionInfo", key = "#accessToken", unless = "#result == null")
    public UserInfoDTO getUserInfo(String loginCode, String sysId, String accessToken) {
        List<Map<String, Object>> users = userCacheMapper.selectUserInfo(loginCode, sysId);
        if (users.isEmpty()) {
            return null;
        }

        UserInfoDTO user = new UserInfoDTO();
        fullUserDto(user, users);
        ObjBean logicSys = new ObjBean(sysId, "", "");
        user.setLogicSys(logicSys);

        return user;
    }

    @Override
    @Transactional(readOnly = true)
    @Cacheable(value = "sessionInfo", key = "'menuandContr_'+#accessToken", unless = "#result == null")
    public MenuContrDTO getMenuandContr(String loginCode, String sysId, String accessToken) {
        MenuContrDTO menuContrDTO = new MenuContrDTO();
        menuContrDTO.setContr(userCacheMapper.selectUserContr(loginCode, sysId,""));
        menuContrDTO.setMenu(userCacheMapper.selectMenu(loginCode, sysId,""));
        return menuContrDTO;
    }

    @Override
    @Transactional(readOnly = true)
//    @Cacheable(value = "sessionInfo", key = "'menuandContr_'+#accessToken", unless = "#result == null")
    public MenuContrDTO getMenuandContrByRoleId(String loginCode, String sysId, String accessToken,String roleId) {
        MenuContrDTO menuContrDTO = new MenuContrDTO();
        menuContrDTO.setContr(userCacheMapper.selectUserContr(loginCode, sysId,roleId));
        menuContrDTO.setMenu(userCacheMapper.selectMenu(loginCode, sysId,roleId));
        return menuContrDTO;
    }

    @Override
    @Transactional(readOnly = true)
    @Cacheable(value = "sessionInfo", key = "'dataContr_'+#accessToken", unless = "#result == null")
    public List<DataContrDTO> getDataAuth(String loginCode, String sysId, String accessToken) {
        List<DataContrDTO> dataContr = new ArrayList<>();
        if (loginCode == null) {
            if (log.isDebugEnabled()) {
                log.debug("The passed in logincode parameter is null, unable to query user data permission information");
            }
        } else {
            dataContr = userCacheMapper.selectDataAuthList(loginCode, sysId);
        }
        return dataContr;
    }

    @Override
    @CacheEvict(value = "contrurl", key = "'getAllContrUrl'", beforeInvocation = true)
    public void cleanAllContrUrlCache() {

    }

    @Override
    @CacheEvict(value = "sessionInfo", key = "#accessToken", beforeInvocation = true)
    public void cleanUserInfoCache(String accessToken) {

    }

    @Override
    @CacheEvict(value = "sessionInfo", key = "'menuandContr_'+#accessToken", beforeInvocation = true)
    public void cleanMenuAndContrCache(String accessToken) {

    }

    @Override
    @CacheEvict(value = "sessionInfo", key = "'dataContr_'+#accessToken", beforeInvocation = true)
    public void cleanDataContrCache(String accessToken) {

    }

    @Autowired
    AdminSmInstuMapper adminSmInstuMapper;

    private void fullUserDto(UserInfoDTO user, List<Map<String, Object>> userT) {
        user.setLoginCode((String) userT.get(0).get("loginCode"));
        user.setLoginTime((String) userT.get(0).get("lastLoginTime"));
        user.setUserAvatar((String) userT.get(0).get("userAvatar"));
        user.setUserCode((String) userT.get(0).get("userId"));
        user.setUserEmail((String) userT.get(0).get("userEmail"));
        user.setUserId((String) userT.get(0).get("userId"));
        user.setUserMobilephone((String) userT.get(0).get("userMobilephone"));
        user.setUserName((String) userT.get(0).get("userName"));

        ObjBean instu = Optional.ofNullable(adminSmInstuMapper.selectByPrimaryKey((String) userT.get(0).get("instuId")))
                .map(temp -> new ObjBean(temp.getInstuId(), temp.getInstuCde(), temp.getInstuName())).orElseGet(() -> {
                    log.warn("Failed to load financial institution,[{}]", (String) userT.get(0).get("instuId"));
                    return new ObjBean();
                });

        user.setInstuOrg(instu);

        ObjBean org = new ObjBean((String) userT.get(0).get("orgId"), (String) userT.get(0).get("orgCode"),
                (String) userT.get(0).get("orgName"));

        if (org.getDetails() == null) {
            org.setDetails(new HashMap());
        }
        org.getDetails().put("orgLevel", (String) userT.get(0).get("orgLevel"));

        user.setOrg(org);

        List<ObjBean> roles = new ArrayList<ObjBean>();
        user.setRoles(roles);
        List<String> ut = new ArrayList<String>();
        for (Map<String, Object> userTT : userT) {
            if (ut.contains((String) userTT.get("roleId"))) {// 去重

            } else {
                ObjBean role = new ObjBean((String) userTT.get("roleId"), (String) userTT.get("roleCode"),
                        (String) userTT.get("roleName"));
                roles.add(role);
                ut.add((String) userTT.get("roleId"));
            }
        }

    }

    @SuppressWarnings("unchecked")
    @Override
    @Cacheable(value = "sessionInfo", key = "'userCode_'+#accessToken", unless = "#result == null")
    public String getUserCode(String accessToken) {
        return AuthUtils.getCurrentUserLogin(AuthUtils.getParsedAccessTokenMap());
    }
}
